#include <iostream>
#include <string>
#include <vector>
#include <cstdlib>
#include <unistd.h>
#include <functional>
#include <sys/wait.h>
#include "Task.hpp"
#include "Channel.hpp"
using work_t = std::function<void()>;
// 先描述
enum
{
    OK = 0,
    UsageError,
    PipeError,
    ForkError
};
class ProcessPool
{
public:
    ProcessPool(int n, work_t w)
        : processnum(n), work(w)
    {
        InitProcessPool();
    }
    // channels输出型参数
    // work:回调方法
    int InitProcessPool()
    {
        for (int i = 0; i < processnum; i++)
        {
            // 1.先创建管道

            int pipefd[2] = {0};
            int n = pipe(pipefd);
            if (n < 0)
                return PipeError;

            pid_t id = fork();
            if (id < 0)
            {
                return ForkError;
            }
            // 建立通信通道
            if (id == 0)
            {
                for (auto &c : channels)
                    c.Close();
                ::close(pipefd[1]);
                dup2(pipefd[0], 0);
                work();
                // Worker(pipefd[0]);
                ::exit(0);
            }
            ::close(pipefd[0]);
            channels.emplace_back(pipefd[1], id);
            // Channel ch(pipefd[1],id);
            // channels.push_back(ch);
        }
        return OK;
    }
    void DispatchTask()
    {
        int who = 0;
        int num = 5;
        while (num--)
        {
            // a.选择任务
            int task = tm.SelectTack();
            // b。选择子进程
            Channel &curr = channels[who++];
            who %= channels.size();

            std::cout << "######################" << std::endl;
            std::cout << "send " << task << " to " << curr.Name() << ", 任务还剩: " << num << std::endl;
            std::cout << "######################" << std::endl;
            // c.派发任务
            curr.Send(task);
            sleep(1);
        }
    }
    void CleanProcessPool()
    {
        for (auto &c : channels)
        {
            c.Close();
            pid_t rid = waitpid(c.Id(), nullptr, 0);
            if (rid > 0)
            {
                std::cout << "child " << rid << " quit ... success" << std::endl;
            }
        }

        // v2
        // for (int i = channels.size() - 1; i >= 0; i--)
        // {
        //     channels[i].Close();
        //     pid_t rid = waitpid(channels[i].Id(), nullptr, 0);
        //     if (rid > 0)
        //     {
        //         std::cout << "child " << rid << " quit ... success" << std::endl;
        //     }
        // }
        // v1
        // for (auto &c : channels)
        // {
        //     c.Close();
        // }
        // for (auto &c : channels)
        // {
        //     pid_t rid = waitpid(c.Id(), nullptr, 0);
        //     if (rid > 0)
        //     {
        //         std::cout << "child " << rid << " quit ... success" << std::endl;
        //     }
        // }
    }
    void DebugPrint()
    {
        for (auto &c : channels)
        {
            std::cout << c.Name() << std::endl;
        }
    }

private:
    std::vector<Channel> channels;
    int processnum;
    work_t work;
};
